#include <REGX52.H>

sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;

#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR   0x84
#define DS1302_DATE   0x86
#define DS1302_MONTH  0x88
#define DS1302_DAY    0x8A
#define DS1302_YEAR   0x8C
#define DS1302_WP     0x8E


char DS1302_time[] = {23, 01, 11, 12, 59, 55, 3};

void DS1302_init(void)
{
    DS1302_CE = 0;
    DS1302_SCLK = 0;
}

void DS1302_writebyte(unsigned char command, Data)
{
    unsigned char i;
    DS1302_CE = 1;
    for (i = 0; i < 8; i++)
    {
        DS1302_IO = command & (0x01 << i);  // 取出第i位，e.g. 写入第1位 0x02 = 00000010，左侧位变量非0即真
        DS1302_SCLK = 1;
        // 如果单片机操作速度很快，此处要加延时
        DS1302_SCLK = 0;
    }
    for (i = 0; i < 8; i++)
    {
        DS1302_IO = Data & (0x01 << i);
        DS1302_SCLK = 1;
        DS1302_SCLK = 0;
    }
    DS1302_CE = 0;
} 
unsigned char DS1302_readbyte(unsigned char command)
{
    unsigned char i, Data = 0x00;
    command |= 0x01;  // 最低位置1，为读的命令
    DS1302_CE = 1;
    for (i = 0; i < 8; i++)
    {
        DS1302_IO = command & (0x01 << i);
        // 调整时序，使命令字读取过程结束而不读取下一个数据
        DS1302_SCLK = 0;
        DS1302_SCLK = 1;
    }
    
    for (i = 0; i < 8; i++)
    {
        DS1302_SCLK = 1;  // 虽然上一步就是高电平，但是这一步保证和时序一致
        DS1302_SCLK = 0;  // 此处MCU释放控制，直接读取IO口状态，移交DS1302控制
        if (DS1302_IO)
        {
            Data |= (0x01 << i);  // 最低位置1，IO口没有读到1的即0自动会左移
        }
    }
    DS1302_CE = 0;
    DS1302_IO = 0;  // 在读之前将IO口置0
    return Data;
}

void DS1302_settime()
{
    DS1302_writebyte(DS1302_WP, 0x00);
    DS1302_writebyte(DS1302_YEAR, DS1302_time[0] / 10 * 16 + DS1302_time[0] % 10);
    DS1302_writebyte(DS1302_MONTH, DS1302_time[1] / 10 * 16 + DS1302_time[1] % 10);
    DS1302_writebyte(DS1302_DATE, DS1302_time[2] / 10 * 16 + DS1302_time[2] % 10);
    DS1302_writebyte(DS1302_HOUR, DS1302_time[3] / 10 * 16 + DS1302_time[3] % 10);
    DS1302_writebyte(DS1302_MINUTE, DS1302_time[4] / 10 * 16 + DS1302_time[4] % 10);
    DS1302_writebyte(DS1302_SECOND, DS1302_time[5] / 10 * 16 + DS1302_time[5] % 10);
    DS1302_writebyte(DS1302_DAY, DS1302_time[6] / 10 * 16 + DS1302_time[6] % 10);
//    DS1302_writebyte(DS1302_WP, 0x80);
}

void DS1302_readtime()
{
    unsigned char temp;
    temp = DS1302_readbyte(DS1302_YEAR);
    DS1302_time[0] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_MONTH);
    DS1302_time[1] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_DATE);
    DS1302_time[2] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_HOUR);
    DS1302_time[3] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_MINUTE);
    DS1302_time[4] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_SECOND);
    DS1302_time[5] = temp / 16 * 10 + temp % 16;
    temp = DS1302_readbyte(DS1302_DAY);
    DS1302_time[6] = temp / 16 * 10 + temp % 16;
}